<template>
  <div role="tablist" :class="cn(tabsVariant({ visual, placement, size }))">
    <template v-for="(tab, index) in tabs" :key="index">
      <a
        role="tab"
        :class="
          cn(
            'tab',
            {
              'tab-active': index === selected,
              'tab-disabled': tab.disabled,
            },
            tabClass
          )
        "
        @click="
          selected = index;
          emit('change', index);
        "
      >
        {{ tab.label }}
      </a>
      <div :class="cn('tab-content', contentClass)">
        <slot :name="tab.name"></slot>
      </div>
    </template>
  </div>
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { cva } from "class-variance-authority";
import { cn } from "../utils";

import type { Size, TabsVisual, TabsModifier, TabsPlacement } from "./types";

export interface TabItem {
  name: string;
  label: string;
  disabled?: boolean;
  active?: boolean;
}

interface Props {
  size?: Size;
  visual?: TabsVisual;
  modifier?: TabsModifier;
  placement?: TabsPlacement;
  tabClass?: string;
  tabs: TabItem[];
  contentClass?: string;
  active?: number;
}

const props = defineProps<Props>();
const emit = defineEmits<{
  (e: "change", value: number): void;
}>();

const tabsVariant = cva("tabs", {
  variants: {
    visual: {
      none: "",
      box: "tabs-box",
      border: "tabs-border",
      lift: "tabs-lift",
    },
    placement: {
      top: "tabs-top",
      bottom: "tabs-bottom",
    },
    size: {
      xs: "tabs-xs",
      sm: "tabs-sm",
      md: "tabs-md",
      lg: "tabs-lg",
      xl: "tabs-xl",
    },
  },
  defaultVariants: {
    visual: "none",
    placement: "top",
    size: "md",
  },
});
// init selected tab
const initSelected =
  props.tabs?.findIndex((tab) => tab.active) ?? props.active ?? 0;
const selected = ref(initSelected < 0 ? 0 : initSelected);
// watch active prop
watch(
  () => props.active,
  (val) => {
    if (val === undefined) return;
    selected.value = val;
  }
);
</script>
